package com.etonenet.base.test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Component;

import com.etonenet.base.entity.Resource;
import com.etonenet.base.entity.ResourceRole;
import com.etonenet.base.repository.ResourceRepository;

/**
 * 对每个fileter做额外的处理，{@link org.springframework.security.web.FilterInvocation
 * FilterInvocation} 为filter句柄，含有request信息。
 * <p>
 * 此调用在AbstractAccessDecisionManager之前
 * <p>
 * Security config 如下：
 * 
 * <pre>
 * .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
		    public <O extends FilterSecurityInterceptor> O postProcess(O fsi) {
		        fsi.setSecurityMetadataSource(metadataSource);
		        return fsi;
		    }
		})
 * </pre>
 * 
 * @author wxu
 * 
 * @see org.springframework.security.web.FilterInvocation FilterInvocation
 *
 * @deprecated 因为可以直接在security config 中使用antMatch等方法配置
 */

@Component
public class MyFilterSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

	private static Logger logger = LoggerFactory.getLogger(MyFilterSecurityMetadataSource.class);

	@Autowired
	private ResourceRepository repository;

	public List<ConfigAttribute> getAttributes(Object object) {
		FilterInvocation fi = (FilterInvocation) object;
		String fullRequestUrl = fi.getFullRequestUrl();
		String requestUrl = fi.getRequestUrl();
		String httpMethod = fi.getRequest().getMethod();
		String contextPath = fi.getRequest().getContextPath();
		// System.out.println("Full request URL: " + fullRequestUrl);
		// System.out.println("Request URL: " + requestUrl);
		// System.out.println("HTTP Method: " + httpMethod);
		// System.out.println("Context path: " + contextPath);
		List<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>(0);
		// Lookup your database (or other source) using this information and
		// populate the list of attributes

		// FIXME 缓存
		List<Resource> list = repository.findAll();
		for (Resource resource : list) {
			// 添加数据库配置，URL授权验证
			RequestMatcher requestMatcher = new AntPathRequestMatcher(resource.getResString());
			if (requestMatcher.matches(fi.getHttpRequest())) {
				logger.info("Matched : {} ", fi.getFullRequestUrl());
				for (ResourceRole resourceRole : resource.getResourceRoles()) {
					configAttributes.add(new SecurityConfig(resourceRole.getRole()));
				}
				break;
			}
		}

		if (configAttributes.isEmpty()) {
			logger.info("NOT Matched : {} ", fi.getFullRequestUrl());
		}
		return configAttributes;
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	public boolean supports(Class<?> clazz) {
		return FilterInvocation.class.isAssignableFrom(clazz);
	}
}